package com.baixiaowen.xiaoaointerview.大厂笔试_白板面试篇.Java8_StreamT接口;

import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ForkJoinPool;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class BasicExamples {

    public static void test_mapFilter() {
//        Stream<Integer> stream =
                Stream.of(1, 2, 3, 4, 5, 6)
                .map(x -> x.toString())
                .map(x -> x + x)
                .map(x -> x + x + x)
//                .map(x -> Integer.parseInt(x))
                .map(Integer::parseInt)
                .forEach(x -> {
                    System.err.println(x);
                });

        // function reference operator
        // lambda expression

//        System.err.println(stream);
    }

    public static void main(String[] args) {
//        test_mapFilter();
//        test_mapFilterReduce();
//        test_mutation();
//        test_flatMap();
        test_parallel();
    }

    public static void test_mapFilterReduce() {
        Integer reduce = Stream.of(1, 2, 3, 4, 5, 6)
                .map(x -> x * x)
                .filter(x -> x < 20)
                .reduce(0, Math::max);

        // Monad
        OptionalInt reduce1 = IntStream.of(1, 2, 3, 4, 5, 6)
                .map(x -> x * x)
                .filter(x -> x < 20)
                .reduce(Integer::max);

        System.err.println(reduce1.isPresent());
        System.err.println(reduce1.getAsInt());
    }

    public static void test_mutation () {
        final Stream<Integer> sorted = Stream.of(1, 3, 5, 2, 3, 4, 5, 6).sorted();
        sorted.forEach(System.err::println);
    }

    // 无副作用
    public static int add(int a, int b) {
        return a + b;
    }

    // 有副作用
    static int c = 0;
    public static int add1(int a, int b) {
        // Side effect
        c ++;
        System.err.println("xxx");
        return a + b;
    }

    public static void test_flatMap() {
        // flatMap : T -> Stream<R>
        // IntStream != Stream<int>
        // int Integer
//        Stream<Object> set =
        Set set = Stream.of("My", "Mine")
                .flatMap(str -> str.chars().mapToObj(i -> (char)i))
                .collect(Collectors.toSet());

        System.err.println(set.stream().collect(Collectors.toList()));
    }

    public static void test_parallel() {
        Random r = new Random();
        List<Integer> collect = IntStream.range(0, 1000_000)
                .map(x -> r.nextInt(10_000_000))
                // 装箱
                .boxed()
                .collect(Collectors.toList());

        long t0 = System.currentTimeMillis();
        System.err.println(collect.stream().max((a, b) -> a - b));
        System.err.println("time: " + (System.currentTimeMillis() - t0));

        t0 = System.currentTimeMillis();
        System.err.println(collect.parallelStream().max((a, b) -> a - b));
        System.err.println("time: " + (System.currentTimeMillis() - t0));

        System.err.println(Runtime.getRuntime().availableProcessors());

        CountDownLatch countDownLatch = new CountDownLatch(1);

        // 使用ForkJoin并发框架，减少并行线程数，从而减少数据拆分次数
        t0 = System.currentTimeMillis();
        ForkJoinPool pool = new ForkJoinPool(2);
        pool.submit(() -> {
            System.err.println(collect.parallelStream().max((a, b) -> a - b));
            countDownLatch.countDown();
        });

        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.err.println("time: " + (System.currentTimeMillis() - t0));

    }

    public static void test_stream() {

        Stream<Integer> result = Stream.of("hello", "world")
                .map(x -> x.length());
    }

}
